/**
 * @copyright 2015 Indie Semiconductor.
 *
 * This file is proprietary to Indie Semiconductor.
 * All rights reserved. Reproduction or distribution, in whole
 * or in part, is forbidden except by express written permission
 * of Indie Semiconductor.
 *
 * @file spi_device.c
 * @Author: Jack.Pan
 * @E-mail:jack.pan@indiemicro.com
 * @Date: 2020/03/18
 */

#include <appConfig.h>
#include <gpio_device.h>
#include <spi_device.h>
#include <atomic.h>
#include <isrfuncs.h>



int8_t SPI_Init(SpiClkDevider_t devider)
{
    GPIO_SFRS->GPIO_CFG[(uint8_t)GPIO_PORT_3].DIR   = (uint8_t)GPIO_DIR_OUTPUT;
    GPIO_SFRS->GPIO_CFG[(uint8_t)GPIO_PORT_4].DIR   = (uint8_t)GPIO_DIR_OUTPUT;
    GPIO_SFRS->GPIO_CFG[(uint8_t)GPIO_PORT_5].DIR   = (uint8_t)GPIO_DIR_INPUT;
    

    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_3].HWMODE = 5U;/* GPIO_PORT_3: SPI Master Clock Out.*/
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_4].HWMODE = 4U;/* GPIO_PORT_4: SPI Master MOSI*/
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_5].HWMODE = 4U;/* GPIO_PORT_5: SPI Master MISO.*/

    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_3].PULLMODE = (uint8_t)GPIO_PULL_UP;
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_4].PULLMODE = (uint8_t)GPIO_PULL_UP;    
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_5].PULLMODE = (uint8_t)GPIO_PULL_UP; 

    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_3].RDENA  = 0U;
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_4].RDENA  = 0U;
    IOCTRLA_SFRS->GPIO[(uint8_t)GPIO_PORT_5].RDENA  = 1U;    
    
    
    SPI_SFRS->SPICTRL.FIFOSOFTRESET = 1U;
    SPI_SFRS->SPICTRL.LPBK = 0U;
    SPI_SFRS->SPICTRL.SCKEXT = ((uint8_t)devider >> 2);
    SPI_SFRS->SPICTRL.SPR    = (uint8_t)devider &0x03U;
    SPI_SFRS->SPICTRL.ENA_REQ = 1U;
    return 0;
}

/*#pragma optimize=none*/
int8_t SPI_SendBuff(uint8_t * const buff, uint16_t length)
{
    uint8_t data = 0U;
    SPI_SFRS->SPICTRL.FIFOSOFTRESET = 1U;
    for (uint16_t i = 0U; i < length; i++){
        SPI_SFRS->TXDATA = buff[i];
        while(SPI_SFRS->SPISTATUS.RXFIFOEMPTY == 1U){}/* waiting for rx  completed*/
        data = SPI_SFRS->RXDATA;
        
    }
    return (int8_t)data;
}

int8_t SPI_ReadBuff(uint8_t * const buff, uint16_t length)
{
    SPI_SFRS->SPICTRL.FIFOSOFTRESET = 1U;
    for (uint16_t i = 0; i < length; i++){
        SPI_SFRS->TXDATA = 0xFFU;
        while(SPI_SFRS->SPISTATUS.RXFIFOEMPTY == 1U){}/* waiting for rx completed */
        buff[i] = SPI_SFRS->RXDATA;
    }
    return 0;
}



uint8_t SPI_ReadWriteOneByte(uint8_t data)
{
    uint8_t temp;

    /* Send data */
    SPI_SFRS->TXDATA = data;
    /*wait TXFIFO empty*/
    while(SPI_SFRS->SPISTATUS.TXFIFOEMPTY==0U){}
    /*wait RXFIFO not empty */
    while(SPI_SFRS->SPISTATUS.RXFIFOEMPTY==1U){}
    /*read data*/
    temp = SPI_SFRS->RXDATA;

    return temp;
}

void SPI_Handler(void)
{
  
  
}